/*
 * Copyright (c) 2018, apexes.net. All rights reserved.
 *
 *         http://www.apexes.net
 *
 */
package net.apexes.commons.guice.tx;

import com.google.common.base.Preconditions;
import com.google.inject.AbstractModule;
import com.google.inject.name.Names;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
 */
public class TxModule extends AbstractModule {
    
    private final Map<String, DataSource> dataSources = new HashMap<>();

    protected TxModule() {
    }
    
    public TxModule(DataSource dataSource) {
        this("", dataSource);
    }

    public TxModule(String name, DataSource dataSource) {
        addDataSource(name, dataSource);
    }
    
    protected void addDataSource(String name, DataSource dataSource) {
        Preconditions.checkNotNull(name, "name");
        if (dataSource instanceof TxDataSource) {
            dataSources.put(name, dataSource);
        } else {
            dataSources.put(name, TxDataSource.of(name, dataSource));
        }
    }
    
    @Override
    protected final void configure() {
        for (Map.Entry<String, DataSource> entry : dataSources.entrySet()) {
            String name = entry.getKey();
            DataSource dataSource = entry.getValue();
            if (name.isEmpty()) {
                bind(DataSource.class).toInstance(dataSource);
            } else {
                bind(DataSource.class).annotatedWith(Names.named(name)).toInstance(dataSource);
            }
        }
        TxInterceptor.bind(binder());
        onConfigure();
    }
    
    protected void onConfigure() {
    }

    public static DataSource txDataSource(DataSource dataSource) {
        return TxDataSource.of(dataSource);
    }

    public static TxModuleBuilder named(String name, DataSource dataSource) {
        return new TxModuleBuilder(name, dataSource);
    }
    
    /**
     *
     */
    public static class TxModuleBuilder {
        private final TxModule module;
        
        private TxModuleBuilder(String name, DataSource dataSource) {
            module = new TxModule();
            module.addDataSource(name, dataSource);
        }
        
        public TxModuleBuilder named(String name, DataSource dataSource) {
            module.addDataSource(name, dataSource);
            return this;
        }
        
        public TxModule build() {
            return module;
        }
    }
    
}
